Skip to content

Comments

feat(dmamap): add DmaMap struct#644

Merged
ytakano merged 6 commits intomainfrom
feat/dmamap
Sep 12, 2025
Merged

feat(dmamap): add DmaMap struct#644
ytakano merged 6 commits intomainfrom
feat/dmamap

Conversation

@Koichi98
Copy link
Contributor

@Koichi98 Koichi98 commented Aug 27, 2025

Description

Summary

This PR introduces a new DMA mapping API (dma_map.rs) that provides a robust abstraction for managing DMA transfers between devices and memory. In short, DmaMap layer transforms memory buffers into appropriate segment lists that conform to device-specific constraints.

Key Features

  • DMA constraint management via DmaConstraints structure (boundary, segment size/count limits, alignment)
  • Bounce buffer support for transfers exceeding device segment limits
  • Zero-copy operation when device constraints are met

Core Components:

  • DmaConstraints: Defines device-specific DMA constraints (max segment size, count, boundary, alignment)
  • DmaMap: Manages the mapping between virtual and physical addresses for DMA
  • DmaSegment: Represents a physically contiguous memory segment

Design Decisions

  1. Transfer size validation without splitting
    Similar to OpenBSD's approach, we expect transfers to be limited before reaching the DMAMap layer.

  2. Dynamic bounce buffer as fallback (not recommended)
    The dynamic bounce buffer allocation using DMAPool::new() is implemented as a safety net to prevent failures, but it's not the intended path. The warning log alerts developers that their device driver should pre-allocate DMA memory to avoid unpredictable runtime overhead.

  3. Simplified segment tracking
    OpenBSD tracks per-segment virtual addresses (_ds_va and _ds_bounce_va) to enable fine-grained copying between original and bounce buffers. AWKernel stores virtual addresses only at the map level (orig_vaddr, owned_memory) because we always allocate bounce buffers as single contiguous segments.

  4. Segment coalescing optimization
    The DMA mapping layer includes segment coalescing logic that merges physically contiguous pages into single segments when possible. While this optimization rarely benefits NVMe controllers (which typically set maxsegsize = PAGESIZE, preventing coalescing), it's implemented to support other device types.

Related links

The implementation is not exactly what OpenBSD does in bus_dma but somewhat similar.

bus_dmamap_load
https://github.com/openbsd/src/blob/95647c95e86787fd3d10394754ce3752dc75799c/sys/arch/amd64/amd64/bus_dma.c#L254

bus_dmamap_unload
https://github.com/openbsd/src/blob/95647c95e86787fd3d10394754ce3752dc75799c/sys/arch/amd64/amd64/bus_dma.c#L499

struct bus_dma_segment
https://github.com/openbsd/src/blob/0f23fd2bd67855dcb0ac92c75619a560be0a8fa1/sys/arch/amd64/include/bus.h#L552

struct bus_dmamap
https://github.com/openbsd/src/blob/0f23fd2bd67855dcb0ac92c75619a560be0a8fa1/sys/arch/amd64/include/bus.h#L649

How was this PR tested?

Notes for reviewers

A bit more details about Design Decisions (Note for myself)

  1. Transfer size validation without splitting
    OpenBSD uses physio() with minphys() to enforce these limits. AWKernel hasn't implemented an equivalent physio layer yet, so this responsibility temporarily falls on upper layers. When a transfer exceeds DmaConstraints::maxsize, we return DmaError::SizeTooLarge rather than attempting to split it. This matches the philosophy that the DMA layer should map what it's given, not make policy decisions about transfer sizes.

  2. Dynamic bounce buffer as fallback
    USB drivers with large segment requirements should use DmaMap::from_dma_pool() with pre-allocated buffers rather than relying on dynamic allocation. This design ensures the system won't fail while making it clear that proper DMA memory management requires upfront allocation. The dynamic path exists primarily for unexpected fragmentation scenarios that shouldn't occur with well-designed drivers.

Signed-off-by: Koichi <koichi.imai.2@tier4.jp>
Signed-off-by: Koichi <koichi.imai.2@tier4.jp>
Signed-off-by: Koichi <koichi.imai.2@tier4.jp>
Signed-off-by: Koichi <koichi.imai.2@tier4.jp>
@Koichi98 Koichi98 marked this pull request as ready for review August 28, 2025 13:37
Signed-off-by: Koichi <koichi.imai.2@tier4.jp>
@Koichi98 Koichi98 requested review from veqcc and ytakano August 29, 2025 02:22
@ytakano ytakano linked an issue Sep 12, 2025 that may be closed by this pull request
@ytakano ytakano merged commit 1e9cbf8 into main Sep 12, 2025
1 check passed
@ytakano ytakano deleted the feat/dmamap branch September 12, 2025 01:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bus_dmamap_sync

3 participants